import requests
import json
from itertools import islice
class Stock:
    def __init__(self, pe, pb,total_value,total_revenue,revenue_growth,roe,profit,total_assets,total_liabilities,operating_cash_flow,net_cash_flow):
        self.pe = pe
        self.pb = pb
        self.total_value = total_value
        self.total_revenue = total_revenue
        self.revenue_growth = revenue_growth
        self.roe = roe
        self.profit = profit
        self.total_assets = total_assets
        self.total_liabilities = total_liabilities
        self.operating_cash_flow = operating_cash_flow
        self.net_cash_flow = net_cash_flow


def convert_float(str):
    try:
        return float(str)
    except ValueError as e:
        return 0
def get_base_info_list():
    #get the stock list sorted by pe and pb
    stock_list = {}
    for index in range(1, 282):
        json_url = f"http://48.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112402508937289440778_1658838703304&pn={index}&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&wbp2u=|0|0|0|web&fid=f3&fs=m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048&fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152&_=1658838703305"
        #print(json_url)
        res = requests.get(json_url)
        result = res.text.split("jQuery112402508937289440778_1658838703304")[1].split("(")[1].split(");")[0]

        result_json = json.loads(result)
        stock_datas = result_json['data']['diff']
        for one_stock in stock_datas:
            stock_code = one_stock["f12"]
            if stock_code.startswith("688") or stock_code.startswith("8"):
                continue
            pe = convert_float(one_stock["f9"])  # shiyinglv
            if pe<=0:
                continue
            pb = convert_float(one_stock["f23"]) #shijinglv
            total_value = convert_float(one_stock["f20"]) #zongshizhi
            stock = Stock(0,0,0,0,0,0,0,0,0,0,0)
            stock.pe = pe
            stock.pb = pb
            stock.total_value = total_value
            stock_list[stock_code] = stock
    print(len(stock_list))
    sorted_by_pe = sorted(stock_list.items(), key=lambda x: x[1].pe)
    sorted_by_pb = sorted(stock_list.items(), key=lambda x: x[1].pb)
    for rank, (stock_code, stock) in enumerate(sorted_by_pe, start=1):
        stock.pe_rank = rank
    for rank, (stock_code, stock) in enumerate(sorted_by_pb, start=1):
        stock.pb_rank = rank
    for stock_code,stock in stock_list.items():
        stock.total_rank = stock.pb_rank*1+stock.pe_rank*1.1
    sorted_by_total_rank = sorted(stock_list.items(), key=lambda x: x[1].total_rank)
    stock_filter_list = {}
    stock_filter_list = dict(islice(sorted_by_total_rank, 1000))
    return stock_filter_list

def get_revenue_data_list(report_date,stock_filter_list):
    #get the revenue and roe and profit
    for index in range(1, 230):
        json_url = f"https://datacenter-web.eastmoney.com/api/data/v1/get?callback=jQuery1123008214875122293064_1726111711346&sortColumns=UPDATE_DATE%2CSECURITY_CODE&sortTypes=-1%2C-1&pageSize=50&pageNumber={index}&reportName=RPT_LICO_FN_CPD&columns=ALL&filter=(REPORTDATE%3D%27{report_date}%27)"
        #print(json_url)
        res = requests.get(json_url)
        result = res.text.split("jQuery1123008214875122293064_1726111711346(")[1].split(");")[0]
        result_json = json.loads(result)
        stock_datas = result_json['result']['data']
        for one_stock in stock_datas:
            stock_code = one_stock["SECURITY_CODE"]
            if stock_code not in stock_filter_list:
                continue
            stock = stock_filter_list[stock_code]
            stock.total_revenue = one_stock["TOTAL_OPERATE_INCOME"]
            if stock_code == '600328':
                print(f"{stock_code} revenue:{stock.total_revenue}, pageNum:{index}")
            stock.revenue_growth = one_stock["YSTZ"]
            stock.roe = one_stock["WEIGHTAVG_ROE"]
            stock.profit = one_stock["PARENT_NETPROFIT"]

def get_liabilities_data_list(report_date,stock_filter_list):
    #get liabilities data
    for index in range(1, 103):
        json_url = f"https://datacenter-web.eastmoney.com/api/data/v1/get?callback=jQuery112309001072675163009_1726113042880&sortColumns=NOTICE_DATE%2CSECURITY_CODE&sortTypes=-1%2C-1&pageSize=50&pageNumber={index}&reportName=RPT_DMSK_FN_BALANCE&columns=ALL&filter=(SECURITY_TYPE_CODE+in+(%22058001001%22%2C%22058001008%22))(TRADE_MARKET_CODE!%3D%22069001017%22)(REPORT_DATE%3D%27{report_date}%27)"
        #print(json_url)
        res = requests.get(json_url)
        result = res.text.split("jQuery112309001072675163009_1726113042880(")[1].split(");")[0]
        result_json = json.loads(result)
        stock_datas = result_json['result']['data']
        for one_stock in stock_datas:
            stock_code = one_stock["SECURITY_CODE"]
            if stock_code not in stock_filter_list:
                continue
            stock = stock_filter_list[stock_code]
            stock.total_assets = one_stock["TOTAL_ASSETS"]
            stock.total_liabilities = one_stock["TOTAL_LIABILITIES"]



def get_cashflow_data_list(report_date,stock_filter_list):
    #get liabilities data
    for index in range(1, 103):
        json_url = f"https://datacenter-web.eastmoney.com/api/data/v1/get?callback=jQuery1123028884304404298367_1726113894629&sortColumns=NOTICE_DATE%2CSECURITY_CODE&sortTypes=-1%2C-1&pageSize=50&pageNumber={index}&reportName=RPT_DMSK_FN_CASHFLOW&columns=ALL&filter=(SECURITY_TYPE_CODE+in+(%22058001001%22%2C%22058001008%22))(TRADE_MARKET_CODE!%3D%22069001017%22)(REPORT_DATE%3D%27{report_date}%27)"
        #print(json_url)
        res = requests.get(json_url)
        result = res.text.split("jQuery1123028884304404298367_1726113894629(")[1].split(");")[0]
        result_json = json.loads(result)
        stock_datas = result_json['result']['data']
        for one_stock in stock_datas:
            stock_code = one_stock["SECURITY_CODE"]
            if stock_code not in stock_filter_list:
                continue
            stock = stock_filter_list[stock_code]
            stock.operating_cash_flow = one_stock["NETCASH_OPERATE"]
            stock.net_cash_flow = one_stock["CCE_ADD"]

def get_mgr_age(stock_code):
    #get president age
    age = "";
    for index in range(1, 103):
        trader_code = "";
        if stock_code.startswith("6"):
            trader_code = "SH"
        else:
            trader_code = "SZ"
        json_url = f"https://datacenter.eastmoney.com/securities/api/data/v1/get?reportName=RPT_F10_ORGINFO_MANAINTRO&columns=SECUCODE%2CSECURITY_CODE%2CORG_CODE%2CPERSON_NAME%2CPOSITION%2CSEX%2CHIGH_DEGREE%2CAGE%2CRESUME%2CINCUMBENT_TIME&quoteColumns=&filter=(SECUCODE%3D%22{stock_code}.{trader_code}%22)&pageNumber=1&pageSize=&sortTypes=&sortColumns=&source=HSF10&client=PC&v=05137601985564813"
        #print(json_url)
        res = requests.get(json_url)
        result = res.text
        result_json = json.loads(result)
        stock_datas = result_json['result']['data']
        for one_stock in stock_datas:
            age = one_stock["AGE"]; 
            break;
    return age

stock_list = get_base_info_list()
#stock_list = {}
#stock = Stock(0,0,0,0,0,0,0,0,0,0,0)
#stock_list["603989"] = stock
get_revenue_data_list("2024-06-30",stock_list)
get_liabilities_data_list("2024-06-30",stock_list)
get_cashflow_data_list("2024-06-30",stock_list)
for stock_code,stock in stock_list.items():
    if stock.total_revenue ==0:
        stock.ps = 0
        print(f"{stock_code} revenue is 0")
    else:  
        stock.ps = stock.total_value/stock.total_revenue
    if stock.total_assets == 0 :
        stock.ey = 0
        print(f"{stock_code} assets is 0")
    else:
        stock.ey = stock.profit/stock.total_assets
    if stock.total_assets == 0:
        stock.liabilities_ratio = 0
    else: 
        stock.liabilities_ratio = stock.total_liabilities/stock.total_assets
    if stock.total_liabilities ==0:
        print(f"{stock_code} liabilities is 0")
        stock.operating_cash_flow_ratio =0
        stock.net_cash_flow_ratio = 0
    else:
        stock.operating_cash_flow_ratio = stock.operating_cash_flow/stock.total_liabilities
        stock.net_cash_flow_ratio = stock.net_cash_flow/stock.total_liabilities
    
sorted_by_ps = sorted(stock_list.items(), key=lambda x: x[1].ps)
sorted_by_roe = sorted(stock_list.items(), key=lambda x: x[1].roe,reverse=True)
sorted_by_ey = sorted(stock_list.items(), key=lambda x: x[1].ey,reverse=True)
sorted_by_liabilities_ratio = sorted(stock_list.items(), key=lambda x: x[1].liabilities_ratio)
sorted_by_operating_cash_flow_ratio = sorted(stock_list.items(), key=lambda x: x[1].operating_cash_flow_ratio,reverse=True)
sorted_by_net_cash_flow_ratio = sorted(stock_list.items(), key=lambda x: x[1].net_cash_flow_ratio,reverse=True)
sorted_by_revenue_growth = sorted(stock_list.items(), key=lambda x: x[1].revenue_growth,reverse=True)
for rank, (stock_code, stock) in enumerate(sorted_by_ps, start=1):
    stock.ps_rank = rank
for rank, (stock_code, stock) in enumerate(sorted_by_roe, start=1):
    stock.roe_rank = rank
for rank, (stock_code, stock) in enumerate(sorted_by_ey, start=1):
    stock.ey_rank = rank
for rank, (stock_code, stock) in enumerate(sorted_by_liabilities_ratio, start=1):
    stock.liabilities_ratio_rank = rank
for rank, (stock_code, stock) in enumerate(sorted_by_operating_cash_flow_ratio, start=1):
    stock.operating_cash_flow_ratio_rank = rank
for rank, (stock_code, stock) in enumerate(sorted_by_net_cash_flow_ratio, start=1):
    stock.net_cash_flow_ratio_rank = rank
for rank, (stock_code, stock) in enumerate(sorted_by_revenue_growth, start=1):
    stock.revenue_growth_rank = rank
for stock_code,stock in stock_list.items():
    stock.total_rank = stock.pb_rank*1+stock.pe_rank*1.1+stock.ps_rank*1.2+stock.ey_rank*1.3+stock.roe_rank*1.3+stock.liabilities_ratio_rank*1.1+stock.operating_cash_flow_ratio_rank*1.1+stock.net_cash_flow_ratio_rank*1.1+stock.revenue_growth_rank*1.1 
sorted_by_total_rank = sorted(stock_list.items(), key=lambda x: x[1].total_rank)
stock_filter_list = {}
stock_filter_list = dict(islice(sorted_by_total_rank, 100))
#for stock_code,stock in stock_filter_list.items():
#    iage = get_mgr_age(stock_code)
#    stock.age = age
for stock_code, stock in stock_filter_list.items():
    print(f"{stock_code},pe:{stock.pe},pb:{stock.pb},ps:{stock.ps},cashflow:{stock.operating_cash_flow_ratio},liabilities:{stock.liabilities_ratio},growth:{stock.revenue_growth},ceo age:{stock.age}")
